package com.kunpan.admin.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.github.pagehelper.PageInfo;
import com.kunpan.admin.common.Enum.BusinessType;
import com.kunpan.admin.common.Enum.FileStatusEnum;
import com.kunpan.admin.common.domain.AjaxResult;
import com.kunpan.admin.common.redis.RedisCache;
import com.kunpan.admin.common.redis.RedisMessagePublisher;
import com.kunpan.admin.constant.RedisMessage;
import com.kunpan.admin.entity.PanFile;
import com.kunpan.admin.entity.dto.MessageDto;
import com.kunpan.admin.entity.dto.PanFileDto;
import com.kunpan.admin.mapper.PanFileMapper;
import com.kunpan.admin.mapper.UserMapper;
import com.kunpan.admin.service.FileOperateService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.*;


@Service
public class FileOperateServiceImpl implements FileOperateService {

    @Autowired
    private PanFileMapper panFileMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisCache redisCache;


    /**
     * 获取回收站的文件列表信息
     */
    @Transactional(readOnly = true)
    @Override
    public AjaxResult getRecycleFileList(PanFileDto panFileDto) {
        panFileDto.setUserId(Integer.valueOf(StpUtil.getLoginId().toString()));
        List<PanFile> list = panFileMapper.selectFileList(panFileDto);
        List<PanFile> panFileList;
        //判断当前是不是查询全部文件(这些文件都会包含目录)，目录是是树形结构
        if (panFileDto.getFileType() == null) {
            //完善数据的树性结构
            panFileList = buildTree(list);
        } else {
            panFileList = list;
        }
        // 使用 PageInfo 获取分页信息
        PageInfo<PanFile> pageInfo = new PageInfo<>(panFileList);
        //将数据分别组装起来
        Map<String, Object> filesMap = new HashMap<>();
        filesMap.put("total", pageInfo.getTotal());
        filesMap.put("list", pageInfo.getList());
        return AjaxResult.success(filesMap);
    }

    /**
     * 批量将文件删除到回收站
     */
    @Override
    public AjaxResult updateFileStatusByIds(Integer[] ids) {
        //1 创建list集合，用于封装所有删除菜单id值
        List<Integer> idList = new ArrayList<>();
        for (Integer id : ids) {
            //2 向idList集合设置删除菜单id
            selectPermissionChildById(id, idList);
            //把当前id封装到list里面
            idList.add(id);
        }
        panFileMapper.updateFileStatusByIds(idList, FileStatusEnum.RECYCLE.getValue(), new Date());
        return AjaxResult.success("删除成功");
    }

    /**
     * 批量还原文件
     */
    @Override
    public AjaxResult restoreFileStatusByIds(Integer[] ids) {
        panFileMapper.updateChildFileStatusByIds(ids, FileStatusEnum.NORMAL.getValue(), new Date());
        return AjaxResult.success("操作成功");
    }


    /**
     * 彻底删除文件
     */
    @Transactional
    @Override
    public AjaxResult deleteCompletelyFile(PanFileDto panFileDto) {
        List<Integer> idList = new ArrayList<>();
        //文件类型是否为非文件夹，是的话，直接删除
        if (panFileDto.getFileType() > 0) {
            idList.add(panFileDto.getId());
            panFileMapper.updateCompletelyFileById(idList, FileStatusEnum.CLEAN.getValue(), new Date());
        } else {
            //2 向idList集合设置删除菜单id
            panFileDto.setFileSize(selectPermissionChildById(panFileDto.getId(), idList));
            //把当前id封装到list里面
            idList.add(panFileDto.getId());
            panFileMapper.updateCompletelyFileById(idList, FileStatusEnum.CLEAN.getValue(), new Date());
        }
        //修改剩余内存
        String userId = StpUtil.getLoginId().toString();
        userMapper.updateUserSpace(Integer.valueOf(userId), -panFileDto.getFileSize());
        //更新用户剩余空间
        String useSpaceKey = String.format(RedisMessage.USER_SPACE_KEY, userId);
        Long useSpace = redisCache.getCacheMapValue(useSpaceKey, userId);
        redisCache.setCacheMapValue(useSpaceKey, userId, useSpace - panFileDto.getFileSize());
        return AjaxResult.success("删除成功");
    }

    /**
     * 移动文件位置
     */
    @Override
    public AjaxResult moveFile(Integer id, Integer parentId) {
        PanFile panFile = new PanFile();
        panFile.setId(id);
        panFile.setParentId(parentId);
        panFile.setUpdateTime(new Date());
        panFileMapper.updateFile(panFile);
        return AjaxResult.success("操作成功");
    }


    //2 根据当前父文件id，查询菜单里面子文件id，封装到list集合
    private Long selectPermissionChildById(Integer parentId, List<Integer> idList) {
        Long totalSize = 0L;
        //查询当前文件里面的子文件
        List<PanFile> childIdList = panFileMapper.selectFileListById(parentId);

        if (childIdList.isEmpty()) {
            return 0L;
        }
        //把childIdList里面菜单id值获取出来，封装idList里面，做递归查询
        for (PanFile child : childIdList) {
            idList.add(child.getId()); // 收集子文件ID
            if (child.getFileType() > 0) {
                // 文件类型，累加大小
                totalSize += child.getFileSize();
            } else {
                // 文件夹类型，递归处理子文件
                totalSize += selectPermissionChildById(child.getId(), idList);
            }
        }
        return totalSize;
    }

    /**
     * 文件重命名
     */
    @Override
    public AjaxResult renameFile(PanFile panFile) {
        Integer checkId = panFileMapper.selectFileByFileTypeAanFileName(panFile.getFileType(), panFile.getFileName());
        if (checkId != null) {
            return AjaxResult.error("文件名已存在");
        }
        panFile.setUpdateTime(new Date());
        if (panFileMapper.updateFile(panFile) > 0) {
            return AjaxResult.success("修改成功");
        }
        return AjaxResult.error("修改失败");
    }

    /**
     * 构造树形结构数据
     */
    public List<PanFile> buildTree(List<PanFile> fileList) {
        Map<Integer, PanFile> fileMap = new HashMap<>();
        List<PanFile> roots = new ArrayList<>();
        for (PanFile file : fileList) {
            if (file.getParentId() == null || file.getParentId() == 0) {
                roots.add(file);
            }
            fileMap.put(file.getId(), file);
        }
        //判断根节点roots是否有数据,如果没有，说明当前不是树性结构，fileList全为子节点数据，提前退出此方法
        if (roots.isEmpty()) {
            return fileList;
        }
        for (PanFile file : fileList) {
            if (file.getParentId() != null) {//判断是否存在父节点
                //将当前数据添加到父节点上
                PanFile parent = fileMap.get(file.getParentId());
                if (parent != null) {//判断父节点的有没有在fileMap中
                    //将所有子文件的大小加起来就是父文件的总大小
//                    Long size = (parent.getFileSize() == null ? 0L : parent.getFileSize()) + (file.getFileSize() == null ? 0L : file.getFileSize());
//                    parent.setFileSize(size);
                    parent.getChildren().add(file);
                } else if (file.getParentId() != 0) {
                    roots.add(file);
                }
            }
        }
        return roots;
    }
}
